package com.ccp.dev.system.configuration.xssrelated;

import com.ccp.dev.core.util.AppUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * 防止跨站脚本攻击过滤器
 */
@WebFilter(filterName = "XSSFilter",urlPatterns = "/*")
public class XSSFilter implements Filter {

    private HashSet<String> staticResource = new HashSet<String>();
    private HashSet<String> doNotXssFilter = new HashSet<String>();

    @Value("${xssFilter.filterStatic}")
    private boolean filterStatic = true;

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        if (AppUtil.getBean("staticResource") instanceof HashSet){
            staticResource = (HashSet<String>) AppUtil.getBean("staticResource");
        }
        if (AppUtil.getBean("doNotXssFilter") instanceof HashSet){
            doNotXssFilter = (HashSet<String>)AppUtil.getBean("doNotXssFilter");
        }
    }

    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if(whetherToFilter(request,doNotXssFilter)){
            chain.doFilter(request, response);
            return;
        }

        if(filterStatic){
            chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
            return;
        }

        if(!whetherToFilter(request,staticResource)){
            chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
            return;
        }

        chain.doFilter(request, response);
    }

    /**
     * 判断资源是否需要过滤
     * @param request  ServletRequest
     * @param set  需要判断的url
     * @return  false 不包含  true 包含
     */
    private boolean whetherToFilter(ServletRequest request,Set<String> set){
        for(String pattern : set){
            RequestMatcher requestMatcher = new AntPathRequestMatcher(pattern);
            if(requestMatcher.matches((HttpServletRequest)request)){
                return true;
            }
        }
        return false;
    }
}
